﻿using System;
using System.Collections.Generic;
using ApplicationGenerator.BusinessModule.Elements;
using ApplicationGenerator.BusinessModule.MetaElements;
using ApplicationGenerator.BusinessModule.Interfaces;

namespace ApplicationGenerator.Forms.Utilities
{
    public class ElementManager
    {
        private List<string> _pathList;
        private Dictionary<string, IModel> _loadedElements;
        private IModelFacade _elementFacade;

        public IMetaModel RootMetaAdapter
        {
            get;
            private set;
        }

        public void RegisterPath(string path)
        {
            if (!_pathList.Contains(path))
            {
                _pathList.Add(path);
            }
        }

        public ElementManager(IMetaModel rootMetaAdapter)
        {
            _pathList = new List<string>();
            _loadedElements = new Dictionary<string, IModel>();
            RootMetaAdapter = rootMetaAdapter;
            _elementFacade = (new FacadeFactory()).CreateModelFacade();
            if (rootMetaAdapter == null)
            {
                throw new Exception("Należy podać meta adapter");
            }
        }

        public void LoadElement(int elementId)
        {
            IModel rootElement = _elementFacade.LoadModel(RootMetaAdapter.ModelName, elementId);
            if (rootElement.ModelInstance == null)
            {
                throw new Exception("Element o id " + elementId.ToString() + " nie istnieje dla modelu " + RootMetaAdapter.ModelName);
            }
            _loadedElements[rootElement.MetaModel.ModelName] = rootElement;

            foreach (IMetaField metaField in rootElement.MetaModel.MetaFieldCollection)
            {
                if (metaField.MetaFieldType == MetaFieldType.Relation)
                {
                    LoadElementInternal(rootElement.GetRelation(metaField.FieldName));
                }
            }
        }

        private void LoadElementInternal(IModel relationElement)
        {
            if (relationElement.ModelInstance == null)
            {
                return;
            }

            _loadedElements[relationElement.MetaModel.ModelName] = relationElement;

            foreach (IMetaField metaField in relationElement.MetaModel.MetaFieldCollection)
            {
                if (metaField.MetaFieldType == MetaFieldType.Relation)
                {
                    LoadElementInternal(relationElement.GetRelation(metaField.FieldName));
                }
            }
        }

        public void Save()
        {
            foreach (KeyValuePair<string, IModel> element in _loadedElements)
            {
                _elementFacade.SaveModel(element.Value);
            }
        }

        public int GetRootModelId()
        {
            IModel rootModel = _loadedElements[RootMetaAdapter.ModelName];
            return (int)rootModel.GetProperty(RootMetaAdapter.PrimaryKeyName);
        }

        public IModel CreateRootElement()
        {
            IModel createdElement = _elementFacade.CreateModel(RootMetaAdapter.ModelName);
            _loadedElements[createdElement.MetaModel.ModelName] = createdElement;
            return createdElement;
        }

        public IModel GetRootModel()
        {
            return _loadedElements[RootMetaAdapter.ModelName];
        }

        public IModel GetElement(string path)
        {
            string[] pathParts = path.Split(new char[] { '.' });
            if (pathParts.Length < 2)
            {
                throw new Exception("Niepoprawna ścieżka: " + path);
            }

            if (_loadedElements.ContainsKey(pathParts[pathParts.Length - 2]))
            {
                return _loadedElements[pathParts[pathParts.Length - 2]];
            }

            return null;
        }

    }
}
